In this notebook we will formulate a simple chance-constrained (CC) Unit Commitment (UC) model and implement it in Julia using the JumpChance package. We will observe the performance of this CC UC model on a three-bus example.
In the following notes for the sake of simplicity, we are going to use a three bus example mirroring the interface between Western and Eastern Texas. This example is taken from R. Baldick, "Wind and Energy Markets: A Case Study of Texas," IEEE Systems Journal, vol. 6, pp. 27-34, 2012.
For this example, we set the following characteristics of generators, transmission lines, wind farms and demands:
Generator 1 | Generator 2 | |
$g_{min}$, MW | 0 | 300 |
$g_{max}$, MW | 1000 | 1000 |
$c^g$, \$/MWh | 50 | 100 |
$c^{g0}$, \$/MWh | 1000 | 0 |
Line 1 | Line 2 | |
$f^{max}$, MW | 100 | 1000 |
x, p.u. | 0.001 | 0.001 |
Wind farm 1 | Wind farm 2 | |
$w^{f}$, MW | 150 | 50 |
$c^{w}$, \$/MWh | 50 | 50 |
Bus 1 | Bus 2 | Bus 3 | |
$d$, MW | 0 | 0 | 1500 |
We modify the UC formulation presented yesterday by including chance constraints.
First, we note that the following constraints remain untouched as they are used to make decision on binary commitment decisions:
To obtain the mathematical formulation of the UC model, we will modify the constraints of the ED model as follows: $$ g^{\min}_{i} \cdot u_{t,i} \leq g_{i} \leq g^{\max}_{i} \cdot u_{t,i}, $$
where $ u_{i} \in \{0;1\}. $ In this constraint, if $ u_{i} = 0$, then $g_{i} = 0$. On the other hand, if $ u_{i} = 1$, then $g^{max}_{i} \leq g_{i} \leq g^{min}_{i}$.
Next, we include chance-constraints accounting for regulation:
$$ P (g_{i} - \alpha_i \cdot \omega \geq g^{\max}) \leq \epsilon_g $$$$ P (g_{i} - \alpha_i \cdot \omega \leq g^{\min}) \leq \epsilon_g $$where $\alpha$ is a participation factor of generator $i$, $\omega$ is a deviation of the actual wind generation from its forecast, and $\epsilon_g$ is a small number. Note that $\omega$ is defined as $\omega \sim N(0, var(\omega))$
In the following cell we define the packages used, including package JumpChance which is used to solve chance constraints.
In [1]:
using JuMP # used for mathematical programming
using Interact # used for enabling the slider
#using Gadfly # used for plotting
using JuMPChance # used for solving chance constraints
using Cbc # integer programming solver
Define the input data for the CC UC model:
In [2]:
# Define some input data about the test system
# Maximum power output of generators
const g_max = [1000 1000]
# Minimum power output of generators
const g_min = [0 300]
# Incremental cost of generators
const c_g = [50 100]
# Fixed cost of generators
const c_g0 = [1000 0]
# Incremental cost of wind generators
const c_w = 0
# Total demand
const d = 1500
# Wind forecast
const w_f = 200
# Variance of wind power
const w_var = 20
# Epsilon threshold
const ϵ_cc =0.05
Out[2]:
The function solving the CC UC model:
In [3]:
function solve_ccuc(g_max, g_min, c_g, c_w, d, w_f,w_var, ϵ_cc)
#Define the unit commitment (UC) model
#uc=ChanceModel(solver=CbcSolver())
uc=ChanceModel()
# Define decision variables
@variable(uc, g_min[i] <= g[i=1:2] <= g_max[i]) # power output of generators
#@defVar(uc, u[i=1:2], Bin) # Binary status of generators
@variable(uc, 0 <= w <= w_f ) # wind power injection
@variable(uc, α[1:2] >= 0) # proportional response coefficients
@indepnormal(uc,ω, mean=0, var=w_var)
# Define the objective function
@objective(uc,Min,sum(c_g[i] * g[i] + c_g0[i] for i=1:2)+ c_w * w)
@constraint(uc, sum(α) == 1)
# Define the constraint on the maximum and minimum power output of each generator
#for i in 1:2
# @constraint(uc, g[i] <= g_max[i] * u[i]) #maximum
# @constraint(uc, g[i] >= g_min[i] * u[i]) #minimum
#end
# Define chance constraints on the power output of each generator in response to wind fluctuations
for i in 1:2
@constraint(uc, g[i]-α[i]*ω <= g_max[i], with_probability=1-ϵ_cc)
end
# Define the constraint on the wind power injection
#@constraint(uc, w <= w_f)
# Define the power balance constraint
@constraint(uc, sum(g[i] for i=1:2) + w == d)
# Solve statement
status = solve(uc, method=:Reformulate)
return status, getvalue(g), getvalue(w), w_f-getvalue(w), [1,1], getvalue(α), getobjectivevalue(uc)
end
#
# Solve the economic dispatch problem
status,g_opt,w_opt,ws_opt,u_opt,α,obj=solve_ccuc(g_max, g_min, c_g, c_w, d, w_f, 20, 0.05)
println("\n")
println("Dispatch of Generators: ", g_opt, " MW")
println("Commitments of Generators: ", u_opt)
println("Dispatch of Wind: ", w_opt, " MW")
println("Wind spillage: ", w_f-w_opt, " MW")
println("Proportional response coefficients: ", α)
println("\n")
println("Total cost: ", obj, "\$")
In the following cell we introduce the manipulator, which can adjust $var(\omega)$, $\epsilon_g$, and $d$. While adjusting these parameters, we observe their impact of the cost and dispatch decisions:
In [4]:
@manipulate for w_var_scale = 0.01:0.01:10, ϵ_cc_scale = 0.01:0.01:10, d_scale = 0.25:0.01:2.0
status,g_opt,w_opt,ws_opt,u_opt,α,obj=solve_ccuc(g_max, g_min, c_g, c_w, d_scale*d, w_f, w_var_scale * w_var, ϵ_cc_scale*ϵ_cc)
HTML("Dispatch of generators: $g_opt<br>"*
"Commitment of generators: $u_opt<br>"*
"Dispatch of wind: $w_opt<br>"*
"Proportional response coefficients: $α<br>"*
"Total cost: $obj")
end
Out[4]:
After discussing the implementation of the CC UC and the usage of the JuMPChance package, we believe you can try to finish the following exercise: